<!--
  异步状态组件
  统一处理异步数据的加载、错误和空状态，提供骨架屏和重试功能
-->
<template>
  <div class="async-state">
    <div v-if="loading" class="state state-loading">
      <slot name="loading">
        <div class="skeleton-group">
          <div class="skeleton" v-for="index in skeletonCount" :key="index" />
        </div>
      </slot>
    </div>
    <div v-else-if="error" class="state state-error">
      <slot name="error" :error="error">
        <p class="message">
          {{ error }}
          <button v-if="retry" type="button" class="retry-button" @click="retry">
            重试
          </button>
        </p>
      </slot>
    </div>
    <div v-else-if="isEmpty" class="state state-empty">
      <slot name="empty">
        <p class="message">{{ emptyMessage }}</p>
      </slot>
    </div>
    <slot v-else />
  </div>
</template>

<script setup>
const props = defineProps({
  loading: {
    type: Boolean,
    default: false,
  },
  error: {
    type: String,
    default: '',
  },
  isEmpty: {
    type: Boolean,
    default: false,
  },
  emptyMessage: {
    type: String,
    default: '暂无数据',
  },
  retry: {
    type: Function,
    default: null,
  },
  skeletonCount: {
    type: Number,
    default: 3,
  },
})

defineExpose({
  retry: props.retry,
})
</script>

<style scoped>
.async-state {
  width: 100%;
}

.state {
  border: 1px dashed #dcdfe6;
  border-radius: 8px;
  padding: 24px;
  text-align: center;
  color: #909399;
}

.state-error {
  border-color: #f56c6c;
  color: #f56c6c;
}

.skeleton-group {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.skeleton {
  height: 18px;
  background: linear-gradient(90deg, #f2f6fc 25%, #e5e9f2 37%, #f2f6fc 63%);
  background-size: 400% 100%;
  border-radius: 6px;
  animation: pulse 1.4s ease infinite;
}

@keyframes pulse {
  0% {
    background-position: 0% 50%;
  }
  100% {
    background-position: -135% 50%;
  }
}

.message {
  margin: 0;
  line-height: 1.6;
}

.retry-button {
  margin-left: 8px;
  padding: 4px 10px;
  border: 1px solid #409eff;
  border-radius: 6px;
  background: transparent;
  color: #409eff;
  cursor: pointer;
  font-size: 14px;
}

.retry-button:hover {
  background: rgba(64, 158, 255, 0.1);
}
</style>

